/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package controler;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import controler.NodeItemControler;
import graph.Edge;
import graph.Graph;
import graph.Node;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
import view.HelpWindow;
import view.MainPanel;
import view.MainWindow;
import view.NodeItem;
import view.ResultWindow;
import view.WelcomeWindow;

/**
 *
 * @author borysfan
 */
public class Controler {
    private ToolboxControler toolboxControler;
    private MainPanelControler mainPanelControler;
    private NodePanelControler nodePanelControler;
    private EdgePanelControler edgePanelControler;
    private NodeItemControler activNodeControler;
    private EdgeItemControler activEdgeControler;
    private ResultControler resultControler = null;
    private Controler instance;
    private boolean showicons=true;
    private boolean showlabels=true;
    private ArrayList<NodeItemControler> edgeNodes = new ArrayList<NodeItemControler>();

    private File openFile=null;
    private MainWindow window;

    public Controler(){
        instance= this;
    }

    private void init(){
        toolboxControler = new ToolboxControler(this);
        mainPanelControler = new MainPanelControler(this);
        nodePanelControler = new NodePanelControler(this);
        edgePanelControler = new EdgePanelControler(this);
        activNodeControler = new NodeItemControler(this);
        activEdgeControler = new EdgeItemControler(this);
        window.addToolboxPanel(toolboxControler.getView());
        window.addMainPanel(mainPanelControler.getView());
        window.addNodePanel(nodePanelControler.getView());
        window.addEdgePanel(edgePanelControler.getView());
        window.addPropertiesPanel();
    }

    public void setView(MainWindow w) {
        window=w;
    }

    public void startApp() {
        initActions();
        init();
        java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
               window.setVisible(true);
               window.setShowIcons(showicons);
               window.setShowLabels(showlabels);
               WelcomeWindow welcome = new WelcomeWindow();
               welcome.setVisible(true);
               //welcome.setAlwaysOnTop(true);
            }
        });
    }

    public ArrayList<NodeItemControler> getNodeList(){
        return edgeNodes;
    }

    public void setResultControler(ResultControler rc){
        resultControler = rc;
    }

    public ResultControler getResultControler(){
        return resultControler;
    }

    public void initActions(){
        window.addSimulationAction(new ShowSimulationWindow());
        window.addCloseAction(new CloseAction());
        window.addNewAction(new NewAction());
        window.setHelpButton(new HelpAction());
        window.setIconsButton(new IconAction());
        window.setLabelButton(new LabelAction());
        window.setOpenAction(new OpenAction());
        window.setSaveAction(new SaveAction());
        window.setSaveAsAction(new SaveAsAction());
        window.setAboutProgramAction(new AboutProgramAction());
        window.setPrintToFileBtn(new PrintAction());
    }

    public void showNodeProperties(NodeItemControler itemNodeControler) {  
        nodePanelControler.setNodeControler(itemNodeControler);
        hideActivNode();
        hideActivEdge();
        activNodeControler=itemNodeControler;
        showActivNode();
        window.addNodePanel(nodePanelControler.getView());
        window.showNodePanel();
        window.repaint();
    }
    public void showEdgeProperties(EdgeItemControler itemEdgeControler) {
        edgePanelControler.setEdgeControler(itemEdgeControler);
        hideActivNode();
        hideActivEdge();
        activEdgeControler = itemEdgeControler;
        showActivEdge();
        window.addEdgePanel(edgePanelControler.getView());
        window.showEdgePanel();
        window.repaint();
    }

     public void showEmptyProperties() {
        hideActivNode();
        hideActivEdge();
        window.showPropertiesPanel();
        window.repaint();
    }

    public void showActivNode(){
        activNodeControler.getNodeItem().setColor(Color.red);
        activNodeControler.getNodeItem().repaint();
    }

    public void hideActivNode(){
        activNodeControler.getNodeItem().setColor(activNodeControler.getModel().getDefColor());
        activNodeControler.getNodeItem().repaint();
    }

    public void showActivEdge(){
        activEdgeControler.getView().setColor(Color.red);
        activEdgeControler.getView().repaint();
    }

    public void hideActivEdge(){
        activEdgeControler.getView().setColor(activEdgeControler.getModel().getDefColor());
        activEdgeControler.getView().repaint();
    }

    
 
    public EdgeItemControler getActivEdgeControler(){
        return activEdgeControler;
    }
    /*ustawia wszystkim nodeItem'om akcje na rysowanie krawedzi miedzy nimi*/
    public void setConnectActions() {
        System.out.println(mainPanelControler.getView().getComponentCount());
        for(int i=0;i<mainPanelControler.getView().getComponentCount();i++){
            Component comp = mainPanelControler.getView().getComponent(i);
            if(comp instanceof NodeItem){
                NodeItem item = (NodeItem)comp;
                NodeItemControler nic = item.getNodeItemControler();
                nic.setConnectActions();
            }
        }
    }

    public void setMoveActions(){
       System.out.println(mainPanelControler.getView().getComponentCount());
        for(int i=0;i<mainPanelControler.getView().getComponentCount();i++){
            Component comp = mainPanelControler.getView().getComponent(i);
            if(comp instanceof NodeItem){
                NodeItem item = (NodeItem) comp;
                NodeItemControler nic = item.getNodeItemControler();
                nic.removeMouseMotions();
                nic.removeMouseListener();
                nic.addMouseMotions();
            }
        }
    }

    public void addNodeEdge(NodeItemControler nic) {
        if(edgeNodes.isEmpty()==true){
            edgeNodes.add(nic);
        }else if(edgeNodes.get(0)!=nic){
            edgeNodes.add(nic);
        }


        if(edgeNodes.size()==2){
            System.out.println("Dodac krawedz");
            NodeItemControler beginNode = edgeNodes.get(0);
            NodeItemControler endNode = edgeNodes.get(1);
            beginNode.addEdge(endNode);
            edgeNodes.clear();
            setMoveActions();
        }
    }

    public MainPanelControler getMainPanel(){
        return mainPanelControler;
    }

    public void saveNodeName(String name,NodePanelControler itemNodeControler) {
        itemNodeControler.getItemControler().saveName(name);
        itemNodeControler.getItemControler().setText(name);
        itemNodeControler.getView().updateUI();
        mainPanelControler.getView().updateUI();
    }

    public void saveNodeLock(boolean lock, NodePanelControler itemNodeControler) {
        itemNodeControler.getItemControler().saveLock(lock);
        itemNodeControler.getView().updateUI();
    }

    

     public void saveEdgeName(String name, EdgePanelControler itemEdgeControler) {
         itemEdgeControler.getItemControler().saveName(name);
         itemEdgeControler.getView().updateUI();
    }

    public void saveEdgeVMax(String edgeVMax, EdgePanelControler itemEdgeControler) {
          itemEdgeControler.getItemControler().saveVMax(edgeVMax);
          itemEdgeControler.getView().updateUI();
    }

    public void saveEdgeLength(String edgeLenght, EdgePanelControler itemEdgeControler) {
          itemEdgeControler.getItemControler().saveLength(edgeLenght);
          itemEdgeControler.getView().updateUI();
    }

    public void saveEdgeNotes(String edgeNotes, EdgePanelControler itemEdgeControler) {
          itemEdgeControler.getItemControler().saveNotes(edgeNotes);
          itemEdgeControler.getView().updateUI();
    }


    public void saveEdgeLock(boolean edgeLock, EdgePanelControler itemEdgeControler) {
          itemEdgeControler.getItemControler().saveLock(edgeLock);
          itemEdgeControler.getView().updateUI();
    }

    public MainWindow getMainWindow() {
        return window;
    }

    public void saveEdgeWeather(int weather, EdgePanelControler itemEdgeControler) {
       itemEdgeControler.getItemControler().saveWeather(weather);
       itemEdgeControler.getView().updateUI();
    }

    public void saveEdgeRoad(int road, EdgePanelControler itemEdgeControler) {
       itemEdgeControler.getItemControler().saveRoad(road);
       itemEdgeControler.getView().updateUI();
    }

     public  void saveEdgeTraffic(int traffic, EdgePanelControler itemEdgeControler) {
       itemEdgeControler.getItemControler().saveTraffic(traffic);
       itemEdgeControler.getView().updateUI();
    }

    public void saveEdgeWeatherSlider(int weatherslider, EdgePanelControler itemEdgeControler) {
       itemEdgeControler.getItemControler().saveWeatherSlider(weatherslider);
       itemEdgeControler.getView().updateUI();
    }

    public void saveEdgeRoadSlider(int roadSlider, EdgePanelControler itemEdgeControler) {
       itemEdgeControler.getItemControler().saveRoadSlider(roadSlider);
       itemEdgeControler.getView().updateUI();
    }


    public void deleteEdge() {
        mainPanelControler.deleteEdge(activEdgeControler);
        window.repaint();
    }
    
       
    public void deleteNode() {
        mainPanelControler.deleteNode(activNodeControler);
        window.repaint();
    }

    public void resetColor(){
        mainPanelControler.resetColor();
    }

    public ToolboxControler getToolboxControler() {
        return toolboxControler;
    }

    public void setShowIcons(boolean show){
        this.showicons=show;
    }

    public boolean getShowIcons(){
        return showicons;
    }

    public void setShowLabels(boolean show){
        this.showlabels=show;
    }

    public boolean getShowLabels(){
        return showlabels;
    }

    public void saveFile(File file){
        Graph g = Graph.getInstance();
        ArrayList<Node> list = g.getNodes();
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;

        try {
           System.err.println(file.getPath());
           fos= new FileOutputStream(file.getPath()); //utworzenie strumienia wyjściowego
           oos = new ObjectOutputStream(fos);  //utworzenie obiektu zapisującego do strumienia


           oos.writeObject(list); //serializacja obiektu
         } catch (FileNotFoundException e) {
           e.printStackTrace();
         } catch (IOException e) {
           e.printStackTrace();
         } finally {
           // zasoby zwalniamy w finally
           try {
             if (oos != null) oos.close();
           } catch (IOException e) {}
           try {
             if (fos != null) fos.close();
           } catch (IOException e) {}

         }
         //utworzenie obiektu zapisującego do strumienia
         openFile = file;
    //serializacja obiektu
    }

    public void loadFile(File file){
        ObjectInputStream in;
        try {
            in = new ObjectInputStream(new FileInputStream(file));
            ArrayList<Node> nodes = (ArrayList<Node>) in.readObject();
            in.close();
            Graph g = Graph.getInstance();
            
            g.clear();
            g.setId(nodes.size());
            ArrayList<NodeItemControler> itemControlers = new ArrayList<NodeItemControler>();
            for(int i=0;i<nodes.size();i++){
                g.addNode(nodes.get(i));
                NodeItemControler item = new NodeItemControler(this);
                itemControlers.add(item);
                item.setModel(nodes.get(i));
                getMainPanel().addNode(item);
            }

            ArrayList<Edge> createEdges = new ArrayList<Edge>();
            for(int i=0;i<nodes.size();i++){
                Node begin = nodes.get(i);
                NodeItemControler beginControler = findControler(begin, itemControlers);
                EdgeItemControler eic = null;
                for(int j=0;j<begin.getEdges().size();j++){
                    Node start = begin.getEdges().get(j).getStart();
                    Node end = begin.getEdges().get(j).getEnd();
                    NodeItemControler startControler = findControler(start, itemControlers);
                    NodeItemControler endControler = findControler(end, itemControlers);
                    if(start.equals(begin)){
                        eic = beginControler.addEdgesToEdgesItems(endControler);
                        System.out.println(begin.getName()+" "+end.getName());
                    }else{
                        eic = beginControler.addEdgesToEdgesItems(startControler);
                        System.out.println(begin.getName()+" "+start.getName());
                    }
                    if(eic!=null){
                        eic.setEdge(begin.getEdges().get(j));
                        getMainPanel().addEdge(eic);
                    }
                }
            }
            

            
         
        } catch (IOException ex) {
            Logger.getLogger(Controler.class.getName()).log(Level.SEVERE, null, ex);
        } catch(ClassNotFoundException ex){
            
        }

    }

    private NodeItemControler findControler(Node n,ArrayList<NodeItemControler> list){
        for(int i=0;i<list.size();i++){
            NodeItemControler item = list.get(i);
            if(item.getModel().equals(n))
                return item;
        }
        return null;
    }



   
    ////////////////////////ACTION LISTENERY

    private class ShowSimulationWindow implements ActionListener{

        public void actionPerformed(ActionEvent e) {
            Graph graph = Graph.getInstance();
            if(graph.getNodes().size()==0){
                JOptionPane.showMessageDialog(window,"Graf nie zawiera żadnych wierzchołków!");
                
            }else{
                SimulationControler controler = new SimulationControler(instance);
                controler.getView().setLocationRelativeTo(window);
            }
        }

    }

    private class CloseAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
            window.dispose();
            System.exit(0);
        }

    }

    private class NewAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
            mainPanelControler.reset();
        }

    }
    private class MyFilter extends javax.swing.filechooser.FileFilter {
        public boolean accept(File file) {
            if(file.isDirectory()) return true;
            String filename = file.getName();
            return filename.endsWith(".jcn");
        }
        public String getDescription() {
            return "*.jcn";
        }
    }

    private class OpenAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.addChoosableFileFilter(new MyFilter());
            int retv = fileChooser.showOpenDialog(window);
            if(retv == JFileChooser.APPROVE_OPTION){
                 mainPanelControler.reset();
                File file = fileChooser.getSelectedFile();
                loadFile(file);
                openFile = file;
            }
            
            
        }

        

    }

    private class SaveAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
            if(openFile!=null){
                saveFile(openFile);
            }else{
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.addChoosableFileFilter(new MyFilter());
                fileChooser.setApproveButtonText("Save");
                int retv = fileChooser.showOpenDialog(window);
                if(retv == JFileChooser.APPROVE_OPTION){
                    File file = fileChooser.getSelectedFile();
                    if(file.getName().endsWith(".jcn")==false){
                        File newFile=new File(file.getPath()+".jcn");
                        file.renameTo(newFile);
                    }
                    saveFile(file);
                }
            }
        }

    }

    private class SaveAsAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.addChoosableFileFilter(new MyFilter());
            fileChooser.setApproveButtonText("Save");
            int retv = fileChooser.showOpenDialog(window);
            if(retv == JFileChooser.APPROVE_OPTION){
                File file = fileChooser.getSelectedFile();
                if(file.getName().endsWith(".jcn")==false){
                    File newFile=new File(file.getPath()+".jcn");
                    file.renameTo(newFile);
                }
                saveFile(file);
            }
        }

    }

    private class HelpAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
           HelpWindow help  = new HelpWindow();
           help.setVisible(true);
        }

    }

    private class AboutProgramAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
            WelcomeWindow welcome = new WelcomeWindow();
            welcome.setVisible(true);
            welcome.setAlwaysOnTop(true);
        }

    }

    private class IconAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
           showicons = window.getShowIcons();
           window.repaint();
        }

    }

    private class LabelAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
           showlabels = window.getShowLabel();          
           window.repaint();
        }

    }

    private class PrintAction implements ActionListener{

        public void actionPerformed(ActionEvent e) {
           Graph graph = Graph.getInstance();
           int w = graph.getWidth()+80;
           int h = graph.getHeight()+80;
           System.out.println("wymiar" + w + " "+h);
           BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
           Graphics2D g = bi.createGraphics();
           g.setColor(Color.WHITE);
           g.fillRect(0, 0, w, h);
           g.setColor(Color.BLACK);
           MainPanel mainPanel = getMainPanel().getView();
           mainPanel.printOnlyGraph(g);
           mainPanel.repaint();
           JFileChooser fileChooser = new JFileChooser();
            fileChooser.addChoosableFileFilter(new MyFilterJpeg());
            fileChooser.setApproveButtonText("Save");
            int retv = fileChooser.showOpenDialog(window);
            if(retv == JFileChooser.APPROVE_OPTION){
                File file = fileChooser.getSelectedFile();
                if(file.getName().endsWith(".jpeg")==false){
                    try{

                    FileOutputStream fos=new FileOutputStream(file.getPath()+".jpeg");
                    JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(fos);
                    jpeg.encode(bi);
                    fos.close();}
                    catch(Exception ex){
                        System.err.println("Blad");
                    }

                }
            }


           }

    }

       private class MyFilterJpeg extends javax.swing.filechooser.FileFilter {
        public boolean accept(File file) {
            if(file.isDirectory()) return true;
            String filename = file.getName();
            return filename.endsWith(".jpeg");
        }
        public String getDescription() {
            return "*.jpeg";
        }
    }

}
